package com.evil.formula.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.evil.formula.antlr4.FormulaBaseVisitor;
import com.evil.formula.antlr4.FormulaParser;
import com.evil.formula.pojo.dto.CalcReqDTO;
import lombok.extern.slf4j.Slf4j;

import java.util.stream.Collectors;

/**
 * TODO 暂不支持数组批量运算
 * @author liyang
 * @date 2023-10-30 17:39
 */
@Slf4j
public class MyFormulaVisitor extends FormulaBaseVisitor<Object> {

    private CalcReqDTO.ExtendInfo params;

    @Override
    public Object visitParens(FormulaParser.ParensContext ctx) {
        log.info("visitParens in");
        return this.visit(ctx.expr());
    }

    @Override
    public Object visitPlusMinus(FormulaParser.PlusMinusContext ctx) {
        log.info("visitPlusMinus in");
        Object value1 = this.visit(ctx.expr(0));
        Object value2 = this.visit(ctx.expr(1));

        value1 = ObjectUtil.defaultIfNull(value1, 0);
        value2 = ObjectUtil.defaultIfNull(value2, 0);

        if (value1 instanceof Number v1) {
            if (value2 instanceof Number v2) {
                switch (ctx.op.getType()) {
                    case FormulaParser.PLUS -> {
                        return NumberUtil.add(v1, v2);
                    }
                    case FormulaParser.MINUS -> {
                        return NumberUtil.sub(v1, v2);
                    }
                }
            }
        }

        return null;
    }

    @Override
    public Object visitCompare(FormulaParser.CompareContext ctx) {
        log.info("visitPlusMinus in");
        Object value1 = this.visit(ctx.expr(0));
        Object value2 = this.visit(ctx.expr(1));
        return null;
    }

    @Override
    public Object visitUnaryOperator(FormulaParser.UnaryOperatorContext ctx) {
        return null;
    }

    @Override
    public Object visitBool(FormulaParser.BoolContext ctx) {
        return switch (ctx.op.getType()) {
            case FormulaParser.TRUE -> true;
            case FormulaParser.FALSE -> false;
            default -> null;
        };
    }

    @Override
    public Object visitDouble(FormulaParser.DoubleContext ctx) {
        String text = ctx.DOUBLE().getText();
        return Double.valueOf(text);
    }

    @Override
    public Object visitList(FormulaParser.ListContext ctx) {
        return ctx.expr().stream().map(this::visit).collect(Collectors.toList());
    }

    @Override
    public Object visitError(FormulaParser.ErrorContext ctx) {
        return null;
    }

    @Override
    public Object visitInt(FormulaParser.IntContext ctx) {
        String text = ctx.INT().getText();
        return Integer.valueOf(text);
    }

    @Override
    public Object visitMulDiv(FormulaParser.MulDivContext ctx) {
        log.info("visitMulDiv in");
        Object value1 = this.visit(ctx.expr(0));
        Object value2 = this.visit(ctx.expr(1));

        value1 = ObjectUtil.defaultIfNull(value1, 0);
        value2 = ObjectUtil.defaultIfNull(value2, 0);

        if (value1 instanceof Number v1) {
            if (value2 instanceof Number v2) {
                switch (ctx.op.getType()) {
                    case FormulaParser.MULTIPLY -> {
                        return NumberUtil.mul(v1, v2);
                    }
                    case FormulaParser.DIVIDE -> {
                        return NumberUtil.div(v1, v2);
                    }
                }
            }
        }
        return null;
    }

    @Override
    public Object visitStr(FormulaParser.StrContext ctx) {
        return ctx.String().getText();
    }

    @Override
    public Object visitNull(FormulaParser.NullContext ctx) {
        return null;
    }

    @Override
    public Object visitFunc(FormulaParser.FuncContext ctx) {
        return null;
    }
}
